import weibo_request as wr
import read_data as rd
import write_data as wd
import time_part as tp
import time






#_______________________________________________________________________________________________________________________
#@ 类
class WEIBO_WRITE_DATA(object):
    #___________________________________________________________________________________________________________________
    #@ 类变量
    obj_weibo_request   = wr.WEIBO_REQUESTS()
    obj_read_txt        = rd.READ_TXT()
    obj_write_excel     = wd.WRITE_EXCEL()
    obj_write_txt       = wd.WRITE_TXT()
    obj_time_part       = tp.TIME_PART()
    #___________________________________________________________________________________________________________________
    #@ 初始化
    def __init__(self):
        pass
    #___________________________________________________________________________________________________________________
    #@ uid    =>    "所有微博"中 对应时间内 的 mid
    def write_mid_by_uid_and_time(self,path_read_txt,path_write_excel,start_time = 0,end_time = 0):
        #// 1. 确定时间参数
        if end_time == 0:
            end_time = time.time()
        if start_time == 0:
            start_time = self.obj_time_part.get_time_by_timepart(end_time,1,'hour',-1)
        print(start_time,'\t',end_time)
        #// 2. 获取 uid-list
        uid_list = self.obj_read_txt.get_data_list(path_read_txt)
        #// 3. 写表头
        excel_header = ['mid','uid']
        self.obj_write_excel.write_data_new(path_write_excel,excel_header)
        #// 4. 逐个 uid
        for uid in uid_list:
            #// 1. 先写入本用户的 uid
            self.obj_write_excel.write_data_add(path_write_excel,[''])
            self.obj_write_excel.write_data_add(path_write_excel,[''])
            self.obj_write_excel.write_data_add(path_write_excel,['',uid])
            #// 2. 本uid 爬虫终端标志（若为true，表示页数超过微博总数）
            time_out_flag = False
            #// 3. 本uid的mid-list
            mid_list = []
            #// 4. 获取数据
            for page in range(100):
                # 休眠3秒，放403，将休眠放到每次请求前，防止因为break和下一个mid之间时间差过小
                time.sleep(3)
                # 提示
                print("获取用户 "+str(uid)+" 所有微博中···，当前第 "+str(page+1)+" 页！")
                # 获取 某uid 某页 的 mblogs
                dataset = self.obj_weibo_request.get_mblogs_by_uid(uid,page+1)
                # 检查 card_type（其实不用挨个检查，最后一页肯定不会有"微博不存在"，而是另起一页），如果不等于9，说明已经没微博了
                if dataset[-1]['card_type'] != 9:
                    break                
                # 循环遍历，筛选时间条件，将子数据放入数据集
                for data in dataset:
                    # 第一页的下标0，不是微博，会出现keyerror
                    try:
                        # 获取微博发布时间，并转化为时间戳
                        m_time_f = time.mktime(time.strptime(data['mblog']['created_at'],"%a %b %d %H:%M:%S +0800 %Y"))
                        if (start_time <= m_time_f) and (m_time_f <= end_time):
                            print(
                                start_time,"\t",
                                m_time_f,"\t",
                                end_time,"\t",
                                m_time_f-start_time,"\t",
                                end_time-m_time_f
                            )
                            # 将dict类型数据直接extend，extend会将其识别为字符串列表，将每个字符当作元素，所以要将其包起来，弄成列表
                            mid_list.extend([data['mblog']['mid']])
                        else:
                            # 如果现在爬到的微博，不在时间范围之内，并且不是链表中第一个（不是置顶微博），则中断爬虫
                            if len(mid_list)>1 :
                                time_out_flag = True
                                break
                    except:
                        pass
                # 写入数据
                for mid in mid_list:
                    self.obj_write_excel.write_data_add(path_write_excel,[mid])
                # 如果中断爬虫的标志亮起，则 break
                if time_out_flag == True:
                    break
    #___________________________________________________________________________________________________________________
    #@ mid    =>    repost_info
        ''' 说明：
            dataset解析：（类型：列表）（元素类型：字典）
                data.data[0].visible
                data.data[0].created_at ------------------------------------------- 转发时间
                data.data[0].id --------------------------------------------------- 转发行为的 ID
                data.data[0].mid -------------------------------------------------- 转发行为的 ID
                data.data[0].can_edit
                data.data[0].show_additional_indication
                data.data[0].text ------------------------------------------------- 转发配文
                data.data[0].source
                data.data[0].favorited
                data.data[0].pic_ids
                data.data[0].pic_types
                data.data[0].is_paid
                data.data[0].mblog_vip_type
                data.data[0].user ------------------------------------------------- 转发者信息
                    data.data[0].user.id ------------------------------------------ 转发者 ID
                    data.data[0].user.screen_name --------------------------------- 转发者 用户名
                    data.data[0].user.profile_image_url
                    data.data[0].user.profile_url
                    data.data[0].user.statuses_count
                    data.data[0].user.verified ------------------------------------ 转发者 是否认证
                    data.data[0].user.verified_type ------------------------------- 转发者 认证类型
                    data.data[0].user.verified_type_ext
                    data.data[0].user.verified_reason
                    data.data[0].user.close_blue_v
                    data.data[0].user.description --------------------------------- 转发者 简介
                    data.data[0].user.gender -------------------------------------- 转发者 性别 { f：女，m：男 }
                    data.data[0].user.mbtype
                    data.data[0].user.urank
                    data.data[0].user.mbrank
                    data.data[0].user.follow_me
                    data.data[0].user.following
                    data.data[0].user.followers_count ----------------------------- 转发者 粉丝数
                    data.data[0].user.follow_count -------------------------------- 转发者 关注数
                    data.data[0].user.cover_image_phone
                    data.data[0].user.avatar_hd
                    data.data[0].user.like
                    data.data[0].user.like_me
                    data.data[0].user.badge
                data.data[0].pid
                data.data[0].pidstr
                data.data[0].retweeted_status ------------------------------------- 被转发 微博 的信息
                    data.data[0].retweeted_status.visible
                    data.data[0].retweeted_status.created_at ---------------------- 被转发 微博 发布时间
                    data.data[0].retweeted_status.id ------------------------------ 被转发 微博　ID
                    data.data[0].retweeted_status.mid ----------------------------- 被转发 微博　ID
                    data.data[0].retweeted_status.can_edit
                    data.data[0].retweeted_status.show_additional_indication
                    data.data[0].retweeted_status.text ---------------------------- 被转发 微博内容
                    data.data[0].retweeted_status.textLength ---------------------- 被转发 微博长度
                    data.data[0].retweeted_status.source
                    data.data[0].retweeted_status.favorited
                    data.data[0].retweeted_status.pic_ids
                    data.data[0].retweeted_status.pic_types
                    data.data[0].retweeted_status.thumbnail_pic
                    data.data[0].retweeted_status.bmiddle_pic
                    data.data[0].retweeted_status.original_pic
                    data.data[0].retweeted_status.is_paid
                    data.data[0].retweeted_status.mblog_vip_type
                    data.data[0].retweeted_status.user ---------------------------- 被转发微博 发布人 信息
                        data.data[0].retweeted_status.user.id --------------------- 发布人 ID
                        data.data[0].retweeted_status.user.screen_name ------------ 发布人 用户名
                        data.data[0].retweeted_status.user.profile_image_url
                        data.data[0].retweeted_status.user.profile_url
                        data.data[0].retweeted_status.user.statuses_count
                        data.data[0].retweeted_status.user.verified --------------- 发布人 是否认证
                        data.data[0].retweeted_status.user.verified_type ---------- 发布人 认证类型
                        data.data[0].retweeted_status.user.verified_type_ext
                        data.data[0].retweeted_status.user.verified_reason
                        data.data[0].retweeted_status.user.close_blue_v
                        data.data[0].retweeted_status.user.description ------------ 发布人 简介
                        data.data[0].retweeted_status.user.gender ----------------- 发布人 性别 { f：女，m：男 }
                        data.data[0].retweeted_status.user.mbtype
                        data.data[0].retweeted_status.user.urank
                        data.data[0].retweeted_status.user.mbrank
                        data.data[0].retweeted_status.user.follow_me
                        data.data[0].retweeted_status.user.following
                        data.data[0].retweeted_status.user.followers_count -------- 发布人 粉丝数
                        data.data[0].retweeted_status.user.follow_count ----------- 发布人 关注数
                        data.data[0].retweeted_status.user.cover_image_phone
                        data.data[0].retweeted_status.user.avatar_hd
                        data.data[0].retweeted_status.user.like
                        data.data[0].retweeted_status.user.like_me
                        data.data[0].retweeted_status.user.badge
                    data.data[0].retweeted_status.picStatus
                    data.data[0].retweeted_status.reposts_count ------------------- 被转发 微博 转发数
                    data.data[0].retweeted_status.comments_count ------------------ 被转发 微博 评论数
                    data.data[0].retweeted_status.attitudes_count ----------------- 被转发 微博 点赞数
                    data.data[0].retweeted_status.pending_approval_count
                    data.data[0].retweeted_status.isLongText ---------------------- 被转发 微博 是否长文本
                    data.data[0].retweeted_status.reward_exhibition_type
                    data.data[0].retweeted_status.hide_flag
                    data.data[0].retweeted_status.mlevel
                    data.data[0].retweeted_status.darwin_tags
                    data.data[0].retweeted_status.mblogtype
                    data.data[0].retweeted_status.more_info_type
                    data.data[0].retweeted_status.cardid
                    data.data[0].retweeted_status.content_auth
                    data.data[0].retweeted_status.pic_num
                    data.data[0].retweeted_status.page_info
                    data.data[0].retweeted_status.pics
                    data.data[0].retweeted_status.bid
                data.data[0].reposts_count
                data.data[0].comments_count
                data.data[0].attitudes_count
                data.data[0].pending_approval_count
                data.data[0].isLongText ------------------------------------------- 转发配文 是否长文本
                data.data[0].reward_exhibition_type
                data.data[0].hide_flag
                data.data[0].mlevel
                data.data[0].darwin_tags
                data.data[0].mblogtype
                data.data[0].more_info_type
                data.data[0].number_display_strategy
                data.data[0].content_auth
                data.data[0].repost_type
                data.data[0].pic_num
                data.data[0].alchemy_params
                data.data[0].raw_text
                data.data[0].bid
            '''
    def write_repost_info_by_mid(self,path_read_txt,path_write_excel):
        # 获取mid列表
        mid_list = self.obj_read_txt.get_data_list(path_read_txt)
        # 写表头
        excel_header = [
            # 被转发微博信息
            '被转微博_ID',
            '被转微博_正文',
            '被转微博_is长文本',
            '被转微博_文本长度',
            '被转微博_发布时间',
            '被转微博_转发量',
            '被转微博_评论数',
            '被转微博_点赞数',
            # 被转发微博-发布人
            '发布人_ID',
            '发布人_昵称',
            '发布人_是否认证',
            '发布人_认证类型',
            # 转发操作
            '转发行为_ID',
            '转发行为_正文',
            '转发行为_is长文本',
            '转发行为_转发时间',
            # 转发人
            '转发人_ID',
            '转发人_昵称',
            '转发人_是否认证',
            '转发人_认证类型'
        ]
        self.obj_write_excel.write_data_new(path_write_excel,excel_header)
        for mid in mid_list:
            for page in range(100):
                # 休眠3秒，放403，将休眠放到每次请求前，防止因为break和下一个mid之间时间差过小
                time.sleep(3)
                # 提示
                print("微博内容ID = "+str(mid)+"，当前第 "+str(page+1)+" 页！")
                # 获取数据
                dataset = self.obj_weibo_request.get_repost_info_by_mid(mid,page+1)
                # 若状态为0，则无数据，爬虫结束
                if dataset['ok'] == 0:
                    break
                # 否则，扩充数据集 dataset（data['data']['data']是一个list）       
                dataset = dataset['data']['data']
                for repost in dataset:
                    self.obj_write_excel.write_data_add(path_write_excel,[
                        # 被转发微博信息
                        repost['retweeted_status']['id'],
                        repost['retweeted_status']['text'],
                        repost['retweeted_status']['isLongText'],
                        repost['retweeted_status']['textLength'],
                        repost['retweeted_status']['created_at'],
                        repost['retweeted_status']['reposts_count'],
                        repost['retweeted_status']['comments_count'],
                        repost['retweeted_status']['attitudes_count'],
                        # 被转发微博-发布人
                        repost['retweeted_status']['user']['id'],
                        repost['retweeted_status']['user']['screen_name'],
                        repost['retweeted_status']['user']['verified'],
                        repost['retweeted_status']['user']['verified_type'],
                        # 转发操作
                        repost['id'],
                        repost['text'],
                        repost['isLongText'],
                        repost['created_at'],
                        # 转发人
                        repost['user']['id'],
                        repost['user']['screen_name'],
                        repost['user']['verified'],
                        repost['user']['verified_type']
                    ])
    #___________________________________________________________________________________________________________________
    #@ uid    =>    user-info
    def write_user_info_by_uid(self,path_read_txt,path_write_excel):
        #// 1. 写入表头
        excel_header = ['ID','昵称','性别','简介','关注数','粉丝数','发表量','是否认证','认证类型','认证信息','mbtype（？）','urank（用户等级）','mbrank（会员等级）']
        self.obj_write_excel.write_data_new(path_write_excel,excel_header)
        #// 2. 获得 id-list
        uid_list = self.obj_read_txt.get_data_list(path_read_txt)
        print(uid_list)
        #// 3. 一些变量（第几条数据）
        count = 0
        #// 4. 循环获取数据
        for uid in uid_list:
            #// 1. 休眠一段时间，防止403
            time.sleep(3)            
            #// 2. 请求数据
            data = self.obj_weibo_request.get_user_info_by_uid(uid)
            #// 3. 处理空ID
            if data['ok'] == 0:
                print("ID 无效！")
                continue            
            #// 4. 进一步定位数据
            dataset = data['data']['userInfo']
            #// 5. 组织数据
            data_userinfo = [
                dataset['id'],              # ID    
                dataset['screen_name'],     # 昵称
                dataset['gender'],          # 性别
                dataset['description'],     # 简介
                dataset['follow_count'],    # 关注数
                dataset['followers_count'], # 粉丝数
                dataset['statuses_count'],  # 发表量（包含转发）
                dataset['verified'],        # 是否认证
                dataset['verified_type']    # 认证类型
            ]
            try:
                data_userinfo.append(dataset['verified_reason'])    # 认证信息
            except KeyError as e:
                data_userinfo.append('')
            data_userinfo.extend([
                dataset['mbtype'],          # mbtype（？）
                dataset['urank'],           # urank（用户等级）
                dataset['mbrank']           # mbrank（会员等级）
            ])
            #// 6. 写入数据
            self.obj_write_excel.write_data_add(path_write_excel,data_userinfo)
            #// 7. 每处理完一次响应，控制台输出提示
            count += 1
            print ("已经获取" + str(count) + "条数据")
    #___________________________________________________________________________________________________________________
    #@ nickname    =>    uid-exact
    def write_uid_by_nickname_and_exact(self,path_read_txt,path_write_excel,path_write_txt):
        #// 1. 写入表头
        excel_header = ['ID','昵称','简介','是否认证','认证类型','认证信息']
        self.obj_write_excel.write_data_new(path_write_excel,excel_header)
        #// 2. 获得 name-list
        name_list = self.obj_read_txt.get_data_list(path_read_txt)
        print(name_list)
        #// 3. 一些变量
        count = 0               # 第几条数据
        write_flag = False      # 数据是否写入表格：True（写入）、False（未写入）
        no_data_name_list=[]    # 创建一个列表，用来存储没有对应数据的文件名
        #_______________________________________________________________________________________________________________
        #// 执行try
        try:
            #// 1. 逐个 name，请求数据
            for name in name_list:
                #// 1. 休眠一段时间，防止403
                time.sleep(3)
                #// 2. 请求数据
                data = self.obj_weibo_request.get_uid_by_nickname_and_exact(name,1)
                #// 3. 检查是否为 空页，如果是，则跳过循环
                if data['ok']==0:
                    no_data_name_list.append(name)
                    print(no_data_name_list)
                    continue
                #// 4. 进一步定位数据
                dataset = data['data']['cards'][1]['card_group'] # 因为只查找第一页，所以不用区分第一页和第二页的下标问题
                #// 5. 精准定位并写到本地
                for j in dataset:
                    #// 1. 定位数据
                    if j['user']['screen_name'] != name:
                        print('（X）'+name+" —— "+j['user']['screen_name'])
                        continue
                    #// 2. 组织对应数据
                    j_data = [
                        j['user']['id'],            # ID
                        j['user']['screen_name'],   # 昵称
                        j['user']['description'],   # 简介
                        j['user']['verified'],      # 是否认证
                        j['user']['verified_type']  # 认证类型
                    ]
                    try:
                        j_data.append(j['user']['verified_reason'])  # 认证信息
                    except KeyError as e:
                        j_data.append('')
                    #// 3. 写入数据
                    self.obj_write_excel.write_data_add(path_write_excel,j_data) # 写入数据
                    write_flag = True       # 写入标志
                    count += 1              # 计数 +1
                    break                   # 跳出循环
                #// 6. 如果没有对应数据，将 name 加入无数据列表
                if write_flag==False:
                    no_data_name_list.append(name)
                write_flag = False          # 重置写入表格标志：False 代表还未写入
                #// 7. 显示进度
                print ("已经获取" + str(count) + "条数据")
        #_______________________________________________________________________________________________________________
        #// 若以上代码 出现异常，执行以下代码
        except:
            #// 2. 整理未匹配数据，写入txt
            self.obj_write_txt.write_data_from_list(path_write_txt,no_data_name_list)
            print("代码运行异常！")
        #_______________________________________________________________________________________________________________
        #// 若以上代码 未出现异常，执行以下代码
        else:
            #// 3. 整理未匹配数据，写入txt
            self.obj_write_txt.write_data_from_list(path_write_txt,no_data_name_list)
            print("代码运行结束，未见异常！")
    #___________________________________________________________________________________________________________________
    #@ nickname    =>    uid-fuzzy
    def write_uid_by_nickname_and_fuzzy(self,path_read_txt,path_write_excel,path_write_txt):
        #// 1. 写入表头
        excel_header = ['ID','昵称','简介','是否认证','认证类型','认证信息']
        self.obj_write_excel.write_data_new(path_write_excel,excel_header)
        #// 2. 获得 name-list
        name_list = self.obj_read_txt.get_data_list(path_read_txt)
        print(name_list)
        #// 3. 一些变量
        count = 0               # 第几条数据
        no_data_name_list=[]    # 创建一个列表，用来存储没有对应数据的文件名
        #_______________________________________________________________________________________________________________
        #// 执行try
        try:
            #// 1. 逐个 name，请求数据
            for name in name_list:
                #// 1. 显示进度 并 计数
                count += 1
                print ("正在获取第 %d 条数据"%count)
                #// 2. 写入每个 name
                for k in range(4):
                    self.obj_write_excel.write_data_add(path_write_excel,[''])
                self.obj_write_excel.write_data_add(path_write_excel,[name])
                #// 3. 获取10页之内的数据
                for i in range(10):                   
                    #// 1. 休眠一段时间，防止403
                    time.sleep(3)
                    #// 2. 请求数据
                    print("当前页 %d"%(i+1))
                    data = self.obj_weibo_request.get_uid_by_nickname_and_fuzzy(name,i+1) # url（page=0、page=1、或者不写，都是page=1）
                    #// 3. 检查是否为 空页，如果是，则跳过循环
                    if data['ok']==0:
                        # i==0，表示一开始就搜不到，而不是搜到了最后一页。这时，要把名字记录下来
                        if i==0:
                            no_data_name_list.append(name)
                            print(no_data_name_list)
                            break
                        # 否则，就是到了没有数据的页，为了不在后面的页，多次time(3)，break
                        else:
                            break                        
                    #// 4. 进一步定位数据
                    try:
                        # 第一页，数据在下标 1
                        dataset = data['data']['cards'][1]['card_group']
                    except IndexError as e:
                        # 其他页，数据在下标 0
                        dataset = data['data']['cards'][0]['card_group']
                    #// 5. 精准定位并写到本地
                    for j in dataset:
                        #// 1. 组织对应数据
                        j_data = [
                            j['user']['id'],            # ID
                            j['user']['screen_name'],   # 昵称
                            j['user']['description'],   # 简介
                            j['user']['verified'],      # 是否认证
                            j['user']['verified_type']  # 认证类型
                        ]
                        try:
                            j_data.append(j['user']['verified_reason'])  # 认证信息
                        except KeyError as e:
                            j_data.append('')
                        #// 2. 写入数据
                        self.obj_write_excel.write_data_add(path_write_excel,j_data) # 写入数据
        #_______________________________________________________________________________________________________________
        #// 若以上代码 出现异常，执行以下代码
        except:
            #// 2. 整理未匹配数据，写入txt
            self.obj_write_txt.write_data_from_list(path_write_txt,no_data_name_list)
            print("代码运行异常！")
        #_______________________________________________________________________________________________________________
        #// 若以上代码 未出现异常，执行以下代码
        else:
            #// 3. 整理未匹配数据，写入txt
            self.obj_write_txt.write_data_from_list(path_write_txt,no_data_name_list)
            print("代码运行结束，未见异常！")